#! /bin/env python
import argparse
import logging
import shutil
import copy, json,re, os
from wheezy.template.engine import Engine
from wheezy.template.ext.core import CoreExtension
from wheezy.template.loader import FileLoader

class TEST:
    pass

class COMMAND:
    pass

class CMD2CTEST(object):

    def __init__(self):
        self.SetArgsLogger()
        self.testlib=[]
        self.template = self.GetTemplate()

    def SetArgsLogger(self):
       parser = argparse.ArgumentParser(description='3D GPU CMD2CTest FLow self.args Parser')
       parser.add_argument('-o', '--output_dir', action='store_true', dest="output_dir", default=None, \
                         help="set the output dir ")
       parser.add_argument('-t', '--test', nargs="+", dest="testlib", \
                         help="give the test list that should be convert")
       parser.add_argument('-i', '--input_dir', action='store', dest="input_dir", default=None,\
                         help="set the input dir")
       parser.add_argument('-b', '--batch', action='store_true', dest="batch", default=False,\
                         help="set the input dir")
       parser.add_argument('-d', '--debug', action='store_true', dest="debug", default=False, \
                         help="enable debug mode")
       parser.add_argument('-m', '--mod', action='store', dest="template", default="mwv208.template", \
                         help="set the test template")
       self.args=parser.parse_args()
    
       self.logger = logging.getLogger(__name__)
    
       if self.args.debug: 
         log_mode = logging.DEBUG
       else:
         log_mode = logging.INFO
       self.logger.setLevel(level = log_mode)
       
       handler = logging.FileHandler("neorun.log.")
       handler.setLevel(log_mode)
       formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
       handler.setFormatter(formatter)
        
       console = logging.StreamHandler()
       console.setLevel(log_mode)
        
       self.logger.addHandler(handler)
       self.logger.addHandler(console)
       
       if self.args.debug:
           logging.debug(self.args)

    def GetTest(self):
        "check the input dir"
        assert os.path.isdir(self.args.input_dir), "src dir %s not existed !"%(self.args.input_dir)

        "check the output dir"
        assert os.path.isdir(self.args.output_dir), "dst dir %s not existed !"%(self.args.input_dir)

        if self.args.batch:
            for root, dirs, files in os.walk(self.args.input_dir):
                for i in dirs:
                    test_path = "%s/%s"%(self.args.input_dir, i)
                    if os.path.isdir(test_path):
                        self.testlib.append(self.GetSrcCmd(test_path, i))
        else:
            for i in self.args.testlib:
                "check the test dir"
                test_path = "%s/%s"%(self.args.input_dir, i)
                assert os.path.isdir(test_path), "test dir %s not existed !"%(test_path)
                self.testlib.append(self.GetSrcCmd(test_path, i))

    def GetSrcCmd(self, path, name): 
        cmd_txt = "%s/cmd.txt"%path
        cmd_in = "%s/cmd.in"%path
        assert os.path.isfile(cmd_in), "No valid cmd in path : %"%path

        if not os.path.isfile(cmd_txt):
            retvar = os.getcwd()
            os.chdir(path)
            pre_cmd = "python cmd_new_process_v3.py"
            os.system(pre_cmd)
            os.chdir(retvar)
        
        "init the test"
        test = TEST()
        setattr(test, "name", name)
        setattr(test, "src", path)
        setattr(test, "dst", "%s/%s"%(self.args.output_dir, name))
        setattr(test, "cmds", [])

        valid_cmd_list = [
                          "CMD_LDFILE", 
                          "CMD_LDFILE_AXI",
                          "CMD_DPFILE",
                          "CMD_DPFILE_AXI",
                          "CMD_CMPHEX",
                          "CMD_RDREG",
                          "CMD_WRREG",
                          "CMD_NOP",
                          "CMD_ISR",
                          "CMD_WAITREG"
                         ]
        cmd_switch = {
                          "CMD_LDFILE":      lambda cmd, infos :   self.CmdLoadFile(cmd, infos), 
                          "CMD_LDFILE_AXI":  lambda cmd, infos :   self.CmdLoadFileAxi(cmd, infos),
                          "CMD_DPFILE":      lambda cmd, infos :   self.CmdDpFile(cmd, infos),
                          "CMD_DPFILE_AXI":  lambda cmd, infos :   self.CmdDpFileAxi(cmd, infos),
                          "CMD_CMPHEX":      lambda cmd, infos :   self.CmdCmpHex(cmd, infos),
                          "CMD_RDREG":       lambda cmd, infos :   self.CmdRdReq(cmd, infos),
                          "CMD_WRREG":       lambda cmd, infos :   self.CmdWrReg(cmd, infos),
                          "CMD_NOP":         lambda cmd, infos :   self.CmdNop(cmd, infos),
                          "CMD_ISR":         lambda cmd, infos :   self.CmdIsr(cmd, infos),
                          "CMD_WAITREG":     lambda cmd, infos :   self.CmdWaitReg(cmd, infos) 
        }

        with open(cmd_txt) as source:
            for line in source.readlines():
                cmd_info = line.split(" ")
                cmd_type = cmd_info[0]
                cmd = COMMAND()
                cmd = cmd_switch[cmd_type](cmd, cmd_info)
                test.cmds.append(cmd)
        return test

    def CmdLoadFile(self, cmd, infos): 
        setattr(cmd, "name", infos[0])
        setattr(cmd, "file", infos[1])
        setattr(cmd, "addr", infos[2])
        setattr(cmd, "len", infos[3])
        return cmd

    def CmdLoadFileAxi(self, cmd, infos):
        setattr(cmd, "name", infos[0])
        setattr(cmd, "file", infos[1])
        setattr(cmd, "addr", infos[2])
        setattr(cmd, "len", infos[3])
        return cmd

    def CmdDpFile(self, cmd, infos):
        setattr(cmd, "name", infos[0])
        setattr(cmd, "file", infos[1])
        setattr(cmd, "addr", infos[2])
        setattr(cmd, "len", infos[3])
        return cmd

    def CmdDpFileAxi(self, cmd, infos):
        setattr(cmd, "name", infos[0])
        setattr(cmd, "file", infos[1])
        setattr(cmd, "addr", infos[2])
        setattr(cmd, "len", infos[3])
        return cmd

    def CmdCmpHex(self, cmd, infos):
        setattr(cmd, "name", infos[0])
        setattr(cmd, "file", infos[1])
        setattr(cmd, "addr", infos[2])
        setattr(cmd, "len", infos[3])
        setattr(cmd, "off", infos[4])
        return cmd

    def CmdRdReq(self, cmd, infos):
        setattr(cmd, "name", infos[0])
        setattr(cmd, "addr", infos[1])
        return cmd

    def CmdWrReg(self, cmd, infos):
        setattr(cmd, "name", infos[0])
        setattr(cmd, "addr", infos[1])
        setattr(cmd, "data", infos[2])
        return cmd

    def CmdNop(self, cmd, infos):
        setattr(cmd, "name", infos[0])
        setattr(cmd, "len", infos[1])
        return cmd

    def CmdIsr(self, cmd, infos):
        setattr(cmd, "name", infos[0])
        setattr(cmd, "addr", infos[1])
        setattr(cmd, "golden", infos[2])
        setattr(cmd, "errmask", infos[3])
        return cmd

    def CmdWaitReg(self, cmd, infos):
        setattr(cmd, "name", infos[0])
        setattr(cmd, "addr", infos[1])
        setattr(cmd, "mask", infos[2])
        setattr(cmd, "golden", infos[3])
        setattr(cmd, "errmask", infos[4])

    def GetTemplate(self):
        "get the template"
        template = "%s/template/%s"%(os.getcwd(), self.args.template) 
        assert os.path.isfile(template), "No template : %s existed!"%(template)
        path = %s/template"%os.getcwd()
        engine = Engine(
          loader = FileLoader([path]),
          extensions=[CoreExtension()]
        )
        return engine.get_template(template)

    def ConvertTest(self, test):
        path = "%s/%s"%(test.dst)
        dst = "%s/test.c"%path
        if os.path.isdir(path):
            shutil.rmtree(path)
        os.makedirs(path)
        fp = open(dst, "w")
        fp.write(self.template.render({"Test":test}))
        fp.close()

    def Convert(self):
        self.GetTest()
        assert len(self.testlib) != 0 , "No test set for tools"   
        for i in self.testlib:
            self.ConvertTest(i)

if __name__ == "__main__":
  try:
    converter=CMD2CTEST()
    converter.Convert()
    os._exit(0)
  except KeyboardInterrupt:
      converter.logger.info("Exit the Test Convert")

  os._exit(0)